package com.echo.im.domain.friend.manager;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.echo.im.common.contant.RedisConstants;
import com.echo.im.common.exception.GlobalException;
import com.echo.im.common.result.ResultEnum;
import com.echo.im.domain.user.manager.UserManager;
import com.echo.im.repository.dao.entity.Friend;
import com.echo.im.repository.dao.entity.User;
import com.echo.im.repository.dao.mapper.FriendMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: echo
 * @time: 2024-08-17
 */
@Component
@RequiredArgsConstructor
@CacheConfig(cacheNames = RedisConstants.IM_CACHE_FRIEND)
public class FriendManager {

    private final FriendMapper friendMapper;
    private final UserManager userManager;

    /**
     * 检查好友
     *
     * @param userId    用户Id
     * @param friendIds 好友Id列表
     */
    public void checkFriends(Long userId, List<Long> friendIds) {
        List<Friend> friends = friendMapper.selectListByUserId(userId);
        List<Friend> friendsList = friendIds.stream()
                .map(id -> friends.stream().filter(f -> f.getFriendId().equals(id)).findFirst().get())
                .collect(Collectors.toList());
        if (friendsList.size() != friendIds.size()) {
            throw new GlobalException(ResultEnum.NOT_FRIEND);
        }
    }


    @Cacheable(key = "#userId1+':'+#userId2")
    public Boolean isFriend(Long userId1, Long userId2) {
        QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Friend::getUserId, userId1)
                .eq(Friend::getFriendId, userId2);
        return friendMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 检查两个用户是否为好友
     *
     * @param userId   用户ID
     * @param friendId 朋友ID
     * @throws GlobalException 如果两个用户不是好友关系，则抛出异常
     */
    public void checkFriend(Long userId, Long friendId) {
        FriendManager proxy = (FriendManager) AopContext.currentProxy();
        if (Boolean.FALSE.equals(proxy.isFriend(userId, friendId))) {
            throw new GlobalException(ResultEnum.NOT_FRIEND);
        }
    }

    /**
     * 更新用户的好友数据：昵称和头像
     *
     * @param userId    用户ID
     * @param friendId  好友ID
     * @param nickName  好友的昵称
     * @param headImage 好友的头像
     */
    public void updateFriendData(Long userId, Long friendId, String nickName, String headImage) {
        checkFriend(userId, friendId);

        UpdateWrapper<Friend> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(Friend::getUserId, userId)
                .eq(Friend::getFriendId, friendId)
                .set(Objects.nonNull(nickName), Friend::getFriendNickName, nickName)
                .set(Objects.nonNull(headImage), Friend::getFriendHeadImage, headImage);

        friendMapper.update(null, updateWrapper);
    }

    /**
     * 查找指定用户的好友
     *
     * @param userId   用户ID
     * @param friendId 好友ID
     * @return 好友对象，如果不存在则抛出异常
     */
    public Friend findFriend(Long userId, Long friendId) {
        QueryWrapper<Friend> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Friend::getUserId, userId)
                .eq(Friend::getFriendId, friendId);
        Friend friend = friendMapper.selectOne(wrapper);
        if (Objects.isNull(friend)) {
            throw new GlobalException(ResultEnum.NOT_FRIEND);
        }
        return friend;
    }

    /**
     * 单向解除好友关系
     *
     * @param userId   用户id
     * @param friendId 好友的用户id
     */
    @CacheEvict(value = "bindFriend", key = "#userId+':'+#friendId")
    public void unbindFriend(long userId, Long friendId) {
        QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Friend::getUserId, userId)
                .eq(Friend::getFriendId, friendId);

        friendMapper.delete(queryWrapper);
    }

    /**
     * 单向绑定好友关系
     *
     * @param userId   用户id
     * @param friendId 好友的用户id
     */
    @CacheEvict(key = "#userId+':'+#friendId")
    public void bindFriend(Long userId, Long friendId) {
        QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Friend::getUserId, userId)
                .eq(Friend::getFriendId, friendId);

        if (friendMapper.selectCount(queryWrapper) == 0) {
            Friend friend = new Friend();
            friend.setUserId(userId);
            friend.setFriendId(friendId);

            User friendInfo = userManager.getById(friendId);

            friend.setFriendHeadImage(friendInfo.getHeadImage());
            friend.setFriendNickName(friendInfo.getNickName());
            friendMapper.insert(friend);
        }
    }

    /**
     * 通过用户 ID 查找用户的好友列表
     *
     * @param userId 用户 ID
     * @return 好友列表
     */
    public List<Friend> findFriendByUserId(Long userId) {
        QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Friend::getUserId, userId);
        return friendMapper.selectList(queryWrapper);
    }
}
